home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / Files / Select Folder w⁄ Gray files / simple.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-07  |  17.8 KB  |  566 lines  |  [TEXT/MPS ]

  1. /***********************************************************************************
  2.                         Simple.c
  3. The simplest C System 7 shell application.  This shell can be very handy for 
  4. debugging and testing things.  Add menu items, add dialogs, add controls, or 
  5. whatever else you need. This sample contains basic application startup and 
  6. event loop handling. Add more features as your needs increase.
  7.  
  8. This sample is High Level Event aware, so you can send and receive AppleEvents
  9. from this application
  10.  
  11. Written  by C.K. Haun <TR>
  12. Apple Developer Tech Support
  13. October 1991, Tokyo, Japan
  14. Of course, Copyright 1991, Apple Computer Inc.
  15.  
  16. Modified for Symantec C by Brian Bechtel, DTS, 1993 © 1993 Apple Computer, Inc.
  17. ***********************************************************************************/
  18.  
  19. #include "Simple.h"
  20.  
  21. /* prototypes */
  22.  
  23. void InitalizeApp(void);
  24. void DoDiskEvents(long dinfo);    /* hi word is error code, lo word is drive number */
  25. void DrawMain(WindowPtr drawIt);
  26. Boolean DoSelected(long val);
  27. void SizeMain(WindowPtr theWindow,short how);
  28. void InitAEStuff(void);
  29. void DoHighLevel(EventRecord *AERecord);
  30. void DoDaCall(MenuHandle themenu, long theit);
  31. void DoDocumentClick(WindowPtr theWindow,EventRecord *theEvent);
  32.  
  33. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  34. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  35. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  36. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  37.  
  38. void SampleHelpDialog(void);
  39.  
  40. WindowPtr AddNewWindow(short theID);
  41.  
  42. void NilProc(void);
  43.  
  44. /* in SFGray.c */
  45. void TestGetFileGray(void);
  46.  
  47. /* globals */
  48. Boolean                gQuit, gInBackground;
  49. unsigned long        gMySleep = 60L;
  50. ProcessSerialNumber    gOurSN;
  51. short                gHelpItem;
  52.  
  53.  
  54. #pragma segment Main
  55. main()
  56. {
  57.     EventRecord myEventRecord;
  58.     WindowPtr twindow;
  59.     short fHit;
  60.     windowCHandle tempWCH;
  61.  
  62.     InitalizeApp();
  63.     do {
  64.         WaitNextEvent(everyEvent, &myEventRecord, gMySleep , nil);
  65.  
  66.         switch (myEventRecord.what) {
  67.             case nullEvent:
  68.  
  69.                 /* no nul processing in this sample */
  70.                 break;
  71.             case updateEvt:
  72.                 /* always check to see if it's my window */
  73.                 /* this may not seem necessary under 7.0, where it's unlikely or impossible for */
  74.                 /* a DA to be in your layer, but there are others  */
  75.                 /* who can stick themselves into your window list, */
  76.                 /* BalloonWriter comes quickly to mind */
  77.                 if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  78.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  79.                     ((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  80.                 }
  81.                 break;
  82.             case mouseDown:
  83.                 /* first see where the hit was */
  84.                 fHit = FindWindow(myEventRecord.where, &twindow);
  85.                 switch (fHit) {
  86.                         Rect limitRect;
  87.                         Str255 tempString;
  88.                         long back;
  89.                     case inDesk:    /* if they hit in desk, then the process manager */
  90.                         break;        /* will switch us out, we don't need to do anything */
  91.                     case inMenuBar:
  92.                         DoSelected(MenuSelect(myEventRecord.where));
  93.                         break;
  94.  
  95.                     case inSysWindow:
  96.                         /* pass to the system */
  97.                         SystemClick(&myEventRecord, twindow);
  98.                         break;
  99.                     case inContent:
  100.                         /* Handle content and control clicks here */
  101.                         if (((WindowPeek)myEventRecord.message)->windowKind 
  102.                                 == kMyDocumentWindow) {
  103.                             /* don't do this unless we have a window open, silly */
  104.                             windowCHandle clicker;
  105.                             clicker = (windowCHandle)GetWRefCon(twindow);
  106.                             /* jump to the content function stored for this window */
  107.                             HLock((Handle)clicker);     /* lock it down so things don't get stupid */
  108.                             ((*clicker)->clickMe)(twindow,&myEventRecord);
  109.                             HUnlock((Handle)clicker);       /* all done */
  110.                         }
  111.  
  112.                         break;
  113.                     case inDrag:
  114.                         DragWindow(twindow, myEventRecord.where, &qd.screenBits.bounds);
  115.                         break;
  116.                     case inGrow:
  117.                         /* Call GrowWindow here if you have a grow box */
  118.                         SetPort(twindow);
  119.                         limitRect = qd.screenBits.bounds;
  120.                         limitRect.top = kMinHeight;
  121.                         GetWTitle(twindow, tempString);
  122.                         /* I'm not letting the user shrink the window so */
  123.                         /* small that the title is truncated */
  124.                         limitRect.left = StringWidth(tempString) + 120;
  125.                         back = GrowWindow(twindow,myEventRecord.where, &limitRect);
  126.  
  127.                         if (back) {
  128.                             if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  129.                                 windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  130.                                 Rect sizeRect = ((WindowPtr)twindow)->portRect;
  131.                                 InvalRect(&sizeRect);
  132.                                 sizeRect.top = sizeRect.bottom - 16;
  133.                                 sizeRect.left = sizeRect.right - 16;
  134.                                 EraseRect(&sizeRect);
  135.                                 InvalRect(&sizeRect);
  136.                                 SizeWindow(twindow, back & 0xffff, back >> 16, true);
  137.                                 ((*tempWCH)->sizeMe)(twindow, (short)nil);
  138.                             }
  139.                         }
  140.  
  141.                         InvalRect(&twindow->portRect);
  142.  
  143.                         break;
  144.                     case inGoAway:
  145.                         /* Click in Close box */
  146.                         if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  147.                             if (TrackGoAway(twindow, myEventRecord.where))
  148.                                 ((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
  149.                         }
  150.                         break;
  151.                     case inZoomIn:
  152.                     case inZoomOut:
  153.                         if (TrackBox(twindow, myEventRecord.where, fHit)) {
  154.                             if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  155.                                 windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  156.                                 SetPort(twindow);
  157.  
  158.                                 ZoomWindow(twindow, fHit, true);
  159.                                 InvalRect(&twindow->portRect);
  160.                                 ((*tempWCH)->sizeMe)(twindow, (short)nil);
  161.                             }
  162.                         }
  163.  
  164.  
  165.                 }
  166.             case mouseUp:
  167.                 /* don't care */
  168.                 break;
  169.                 /* same action for key or auto key */
  170.             case keyDown:
  171.             case autoKey:
  172.                 if (myEventRecord.modifiers & cmdKey)
  173.                     DoSelected(MenuKey(myEventRecord.message & charCodeMask));
  174.                 break;
  175.             case keyUp:
  176.                 /* don't care */
  177.                 break;
  178.             case diskEvt:
  179.                 /* I don't do anything special for disk events, this just passes them */
  180.                 /* to a function that checks for an error on the mount */
  181.                 DoDiskEvents(myEventRecord.message);
  182.                 break;
  183.             case activateEvt:
  184.                 if (myEventRecord.modifiers & activeFlag && ((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  185.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  186.                     ((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  187.                 }
  188.                 break;
  189.             case networkEvt:
  190.                 /* don't care */
  191.                 break;
  192.             case driverEvt:
  193.                 /* don't care */
  194.                 break;
  195.             case app4Evt:
  196.                 switch ((myEventRecord.message >> 24) & 0x0FF) {     /* high byte of message */
  197.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  198.                         gInBackground = (myEventRecord.message & kResumeMask) == 0;
  199.                         if(!gInBackground){
  200.  
  201.                         }
  202.                         break;
  203.                 }
  204.                 break;
  205.             default:
  206.                 break;
  207.                 /* This dispatches high level events (AppleEvents, for example) */
  208.                 /* to our dispatch routine.  This is NEW in the event loop for */
  209.                 /* System 7 */
  210.             case kHighLevelEvent:
  211.                 DoHighLevel(&myEventRecord);
  212.                 break;
  213.  
  214.         }
  215.     }
  216.     while (gQuit != true);
  217.  
  218. }
  219.  
  220. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  221. /* like to perform some action or just know when a DA is opened in your */
  222. /* layer.  Can be handy to track memory problems when a DA is opened */
  223. /* with an Option-open */
  224. void DoDaCall(MenuHandle themenu, long theit)
  225. {
  226.     long qq;
  227.     Str255 DAname;
  228.     GetItem(themenu, theit, DAname);
  229.     qq = OpenDeskAcc(DAname);
  230. }
  231.  
  232. /* end DoDaCall */
  233.  
  234. /* DoDiskEvents just checks the error code from the disk mount, */
  235. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  236. /* You can do much more here if you care about what disks are */
  237. /* in the drive */
  238. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  239. {
  240.     short hival, loval, tommy;
  241.     Point fredpoint =  {
  242.         40, 40
  243.     };
  244.     hival = HiWord(dinfo);
  245.     loval = LoWord(dinfo);
  246.     if (hival != noErr)                                     /* something happened */ {
  247.         tommy = DIBadMount(fredpoint, dinfo);
  248.     }
  249. }
  250.  
  251. /* draws my window.  Pretty simple */
  252. void DrawMain(WindowPtr drawIt)
  253. {
  254.     RgnHandle tempRgn;
  255.     Rect scratchRect;
  256.     BeginUpdate(drawIt);
  257.     SetPort(drawIt);
  258.     scratchRect = drawIt->portRect;
  259.     scratchRect.top = scratchRect.bottom - 15;
  260.     scratchRect.left = scratchRect.right - 15;
  261.     tempRgn = NewRgn();
  262.     GetClip(tempRgn);
  263.     ClipRect(&scratchRect);
  264.     DrawGrowIcon(drawIt);
  265.     SetClip(tempRgn);
  266.     DisposeRgn(tempRgn);
  267.  
  268.  
  269.     EndUpdate(drawIt);
  270. }
  271.  
  272. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  273. /* mught be handy someday */
  274. /* I usually use it in an application to determine if a keystroke was accepted */
  275. /* by a menu or whether it should be passed along to any other key acceptors */
  276. Boolean DoSelected(long val)
  277. {
  278.     short loval, hival;
  279.     Boolean returnVal = false;
  280.     loval = LoWord(val);
  281.     hival = HiWord(val);
  282.  
  283.     switch (hival) {                                        /* switch off the menu number selected */
  284.         case kAppleMenu:                                    /* Apple menu */
  285.             if (loval != 1) {                               /* if this was not About, it's a DA */
  286.                 DoDaCall(GetMHandle(kAppleMenu), loval);
  287.             }
  288.             else {
  289.                 Alert(kAboutBox, nil);                      /* do about box */
  290.             }
  291.             returnVal = true;
  292.             break;
  293.         case kFileMenu:                                     /* File menu */
  294.             switch (loval) {
  295.                 case kQuitItem:
  296.                     gQuit = true;                           /* only  item */
  297.                     returnVal = true;
  298.                     break;
  299.                 default:
  300.                     break;
  301.             }
  302.             break;
  303.         case kEditMenu:
  304.             /* edit menu junk */
  305.             /* don't care */
  306.             switch(loval){
  307.                 default:
  308.                     break;
  309.             }
  310.             break;
  311.         case kToolsMenu:
  312.             /* add all your test stuff here */
  313.             switch(loval){
  314.                 case 1:
  315.                     TestGetFileGray();
  316.                     break;
  317.                 case 2:
  318.                     TestGetFileNoGray();
  319.                     break;
  320.                 default:
  321.                     break;
  322.             }
  323.  
  324.             break;
  325.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  326.             /* I only care about this item.  If anything else is returned here, I don't know what */
  327.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  328.             /* Apple reserves the right to add and change things in the Help menu */
  329.             if (loval == gHelpItem)
  330.                 SampleHelpDialog();
  331.             break;
  332.  
  333.     }
  334.     HiliteMenu(0);
  335.     return(returnVal);
  336. }
  337.  
  338.  
  339. void DoDocumentClick(WindowPtr theWindow,EventRecord *theEvent)
  340. {
  341.  
  342. }
  343.  
  344.  
  345. /* InitAEStuff installs my appleevent handlers */
  346. void InitAEStuff(void)
  347. {
  348.     AEinstalls HandlersToInstall[] =  {
  349.         {
  350.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  351.         }
  352.         ,  {
  353.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  354.         }
  355.         ,  {
  356.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  357.         }
  358.         ,  {
  359.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  360.         }
  361.         ,
  362.         /* The above are the four required AppleEvents. */
  363.  
  364.     };
  365.  
  366.     OSErr aevtErr = noErr;
  367.     long aLong = 0;
  368.     Boolean gHasAppleEvents = false;
  369.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  370.      *   then we exit */
  371.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  372.     /* The following series of calls installs all our AppleEvent Handlers.
  373.      *   These handlers are added to the application event handler list that
  374.      *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  375.      *   and we call AEProcessEvent, the AppleEvent manager will check our
  376.      *   list of handlers and dispatch to it if there is one.
  377.      */
  378.     if (gHasAppleEvents) {
  379.         register qq;
  380.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  381.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  382.             HandlersToInstall[qq].theProc, 0, false);
  383.             if (aevtErr) {
  384.                 ExitToShell();                              /* just fail, baby */
  385.             }
  386.         }
  387.     }
  388.     else {
  389.         ExitToShell();
  390.     }
  391. }
  392.  
  393. /* end InitAEStuff */
  394. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  395. /* easy for me to say, huh? */
  396. void DoHighLevel(EventRecord *AERecord)
  397. {
  398.     OSErr myErr;
  399.     myErr=AEProcessAppleEvent(AERecord);
  400.  
  401. }
  402.  
  403. /* end DoHighLevel */
  404.  
  405. /* This is the standard Open Application event.  */
  406. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  407. {
  408.     WindowPtr myWindow;
  409.  
  410. #pragma unused (messagein,reply,refIn)
  411.     /* we of course don't do anything here in this simple app */
  412.     /* except open our window */
  413.     myWindow = AddNewWindow(kDocWindowResID);
  414.  
  415.     return(noErr);
  416. }
  417.  
  418. /* end AEOpenHandler */
  419.  
  420. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  421. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  422. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  423. /* handler will get called. Which means you don't do any initialization of globals here, or */
  424. /* anything else except open then doc.  */
  425. /* SO-- Do NOT assume that you are at app start time in this */
  426. /* routine, or bad things will surely happen to you. */
  427.  
  428. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  429. {
  430. #pragma unused (messagein,refIn,reply)
  431.     /* we of course don't do anything here */
  432.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  433. }
  434.  
  435. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  436. {                                                           /* no printing handler in yet, so we'll ignore this */
  437.     /* the operation is functionally identical to the ODOC event, with the additon */
  438.     /* of calling your print routine.  */
  439. #pragma unused (messagein,refIn,reply)
  440.     /* we of course don't do anything here */
  441.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  442. }
  443.  
  444. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  445. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  446. /* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
  447. /* come through DTS that calls ExitToShell from quit handlers.  Let me explain... */
  448. /* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
  449. /* 100% in your application world.  A5 is right, you can call any toolbox function, */
  450. /* you can call your own routines, everything _seems_ like you are in complete  */
  451. /* control.  Well, almost but not quite.  The routine has been dispatch to from the */
  452. /* AppleEvent Manager's space, so you _must_ return to that at some point! */
  453. /* Which is why you can't call ETS from here.  When you call ExitToShell from an */
  454. /* AE Handler, the most likely thing that happens is the FInder quits, and your  */
  455. /* application keeps running.  Which ain't what you want, y'know? */
  456. /* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
  457. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  458. {
  459. #pragma unused (messagein,refIn,reply)
  460.     gQuit = true;
  461.     return(noErr);
  462. }
  463.  
  464.  
  465.  
  466. /* This is my sample help dialog.  Does not do anything, expand as you need */
  467. void SampleHelpDialog(void)
  468. {
  469.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  470.     short itemhit = 0;
  471.     while (itemhit != 1) {
  472.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  473.     }
  474.     DisposDialog(tdial);
  475. }
  476.  
  477. #pragma segment Initialize
  478. void InitalizeApp(void)
  479. {
  480.     Handle myMenu;
  481.     MenuHandle helpHandle,appleMenuHandle;
  482.     Handle helpString;
  483.     short count;
  484.     long vers;
  485.     MaxApplZone();
  486.     InitGraf((Ptr)&qd.thePort);
  487.     InitFonts();
  488.     InitWindows();
  489.     InitMenus();
  490.     TEInit();
  491.     InitDialogs(nil);
  492.     InitCursor();
  493.     /* Check system version */
  494.     Gestalt(gestaltSystemVersion, &vers);
  495.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  496.     if (vers < 7) {
  497.         StopAlert(kBadSystem, nil);
  498.         ExitToShell();
  499.     }
  500.     InitAEStuff();
  501.     /* set up my menu junk */
  502.     myMenu = GetNewMBar(kMBarID);
  503.     SetMenuBar(myMenu);
  504.     appleMenuHandle = GetMHandle(kAppleMenu);
  505.     AddResMenu(appleMenuHandle, 'DRVR');
  506.  
  507.     /* now install my Help menu item in the Help Manager's menu */
  508.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  509.     count = CountMItems(helpHandle);                        /* How many items are there? */
  510.     helpString = (Handle)GetString(kHelpString);            /* get my help string */
  511.     DetachResource(helpString);                             /* detach it */
  512.     HNoPurge(helpString);
  513.     MoveHHi(helpString);
  514.     HLock(helpString);
  515.     InsMenuItem(helpHandle, (StringPtr)*helpString, count + 1);       /* insert my item in the Help menu */
  516.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  517.  
  518.     DrawMenuBar();
  519.  
  520.  
  521.  
  522.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  523.  
  524. }
  525.  
  526.  
  527. #pragma segment Main
  528. WindowPtr AddNewWindow(short theID)
  529. {
  530.     windowCHandle setControls;
  531.     WindowPtr tempWP;
  532.     short cnt = 0;
  533.     Str31 wtitle;
  534.     tempWP = GetNewWindow(theID, 0, (WindowPtr)-1);        /* get a new window */
  535.     ((WindowPeek)tempWP)->windowKind = kMyDocumentWindow;     /* mark it as my document window */
  536.     setControls = (windowCHandle)NewHandleClear(sizeof(windowControl));       /* add our control structure to it */
  537.     SetWRefCon(tempWP,(long)setControls);    /* stop stuffing refCon directly <ckh 1.0.3> */
  538.     HLock((Handle)setControls);                             /* lock it down while we fill it*/
  539.  
  540.     /* add pointers to our procedures for drawing, saving, and closing */
  541.     /* This way, all I need is one dispatch point for drawing, closing */
  542.     /* or whatever, I don't have to case off the window kind to go to the  */
  543.     /* correct routine.  Kinda like object-oriented programming, but I won't */
  544.     /* admit that. */
  545.     (*setControls)->drawMe = DrawMain;
  546.     (*setControls)->clickMe = DoDocumentClick;
  547.     (*setControls)->sizeMe = SizeMain;
  548.     (*setControls)->generalData = NewHandle(0);
  549.     return(tempWP);
  550. }
  551.  
  552. void SizeMain(WindowPtr theWindow,short how)
  553. {
  554.     WindowPtr tempWP;
  555.     GetPort(&tempWP);
  556.     InvalRect(&theWindow->portRect);
  557.     SetPort(tempWP);
  558. }
  559.  
  560. void NilProc(void)
  561. {
  562.  
  563. }
  564.  
  565.  
  566.